home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / public / bit / src / flist.c < prev    next >
C/C++ Source or Header  |  1994-08-01  |  9KB  |  431 lines

  1. /*
  2.  * $Id: flist.c,v 0.91 1994/02/20 00:52:55 zhao Pre-Release $
  3.  *
  4.  *. This file is part of BIT shareware package. After the two weeks of
  5.  *  free evaluation period, you are encouraged (required) to register
  6.  *  your copy for a small registration fee, which is $35 for personal use
  7.  *  and $50 for commercial, government and institutional use.
  8.  *
  9.  *  Copyright(c) 1993, 1994 by T.C. Zhao.
  10.  *  All rights reserved.
  11.  *
  12.  *  Permission to use, copy, and distribute this software in its entirety
  13.  *  for non-commercial purposes is hereby granted, provided that the
  14.  *  above shareware and copyright notices and this permission notice
  15.  *  appear in all copies and their documentation.
  16.  *
  17.  *  This software may be modified for your own use, but modified versions
  18.  *  may not be distributed without prior consent of the author.
  19.  *
  20.  *  This software is provided "as is" without expressed or implied
  21.  *  warranty of any kind.
  22.  *
  23.  *.
  24.  *
  25.  * Active file list stuff. Standard keyed doubly linked list. The only
  26.  * missing function is append_dlist, which bit does not need.
  27.  * It would be nice if hashed ...
  28.  *
  29.  * All static function needs not to check parameters
  30.  */
  31. #if !defined(lint) && defined(F_ID)
  32. char *id_flist = "$Id: flist.c,v 0.91 1994/02/20 00:52:55 zhao Pre-Release $";
  33. #endif
  34.  
  35. #include "bit.h"
  36. #include "dmalloc.h"
  37.  
  38. /* file list */
  39. typedef struct flist_
  40.   {
  41.       struct flist_ *prev;
  42.       struct flist_ *next;
  43.       char fname[MAXFLEN];
  44.   }
  45. FL;
  46.  
  47. /* directory list */
  48. typedef struct
  49.   {
  50.       struct flist_ *head, *tail;
  51.       char dname[MAXDLEN];
  52.   }
  53. DL;
  54.  
  55. static FL *
  56. create_node(size_t nbytes)
  57. {
  58.     FL *p;
  59.  
  60.     if ((p = malloc(nbytes)))
  61.       {
  62.       p->prev = p->next = 0;
  63.       p->fname[0] = '\0';
  64.       }
  65.  
  66.     return p;
  67. }
  68.  
  69. static void
  70. free_node(FL * node)
  71. {
  72.     node->fname[0] = '\0';
  73.     free(node);
  74. }
  75.  
  76. /*****************************************************************
  77.  * given a filename and flist head, find and return the node  that
  78.  * contains filename
  79.  *****************************************************************/
  80.  
  81. static FL *
  82. dl_search(FL * head, const char *str)
  83. {
  84.     register FL *p;
  85.  
  86.     for (p = head; p && strcmp(p->fname, str); p = p->next)
  87.     ;
  88.     return p;
  89. }
  90.  
  91. /****** free a doubley-linked flist *****/
  92.  
  93. static void
  94. dl_free(FL * head)
  95. {
  96.     FL *p, *q;
  97.  
  98.     for (p = head; p; p = q)
  99.       {
  100.       q = p->next;
  101.       free_node(p);
  102.       }
  103. }
  104.  
  105. #define MAXDIR  10        /* max directories */
  106. static DL dlist[MAXDIR];
  107. #ifdef FLIST_DBG
  108. static int flist_msg_level = 0;
  109. #else
  110. static int flist_msg_level = 1;
  111. #endif
  112.  
  113. /**************************************************************
  114.  * error messages, subject to msg_level filtering:
  115.  * 0 is considered by the message generating routine to be
  116.  * a warning, while 1 is considered to be a nice-to-have
  117.  * information and by default will not be printed.
  118.  **************************************************************/
  119.  
  120. static void
  121. flist_msg(const char *func, const char *dir, const char *f)
  122. {
  123.     M_msg(flist_msg_level, __FILE__, -1)
  124.     (func, "dir=%s\t\tf=%s", dir ? dir : "null", f ? f : "null");
  125. }
  126.  
  127. /*******************************************************************
  128.  * Insert file f from directory dir to the active file list
  129.  *******************************************************************/
  130.  
  131. int
  132. add_to_list(const char *dir, const char *f)
  133. {
  134.     int slot;
  135.     static int warned;
  136.     FL *p;
  137.     DL *q = dlist, *qs;
  138.  
  139.     if (!dir || !f || !*f)
  140.     return -1;
  141.  
  142.     flist_msg("add", dir, f);
  143.  
  144.     /* search for master head */
  145.     for (slot = 0, qs = q + MAXDIR; !slot && q < qs; q++)
  146.     slot = (!q->head || !q->dname[0] || !strcmp(q->dname, dir));
  147.  
  148.     if (!slot)
  149.       {                /* no available space for this dir */
  150.       if (!warned)
  151.         {
  152.         Bark("AddToFlist", "No directory slot left");
  153.         warned = 1;    /* bitching more than once is distasteful */
  154.         }
  155.       return -1;
  156.       }
  157.     /* ok. Insert file */
  158.     --q;            /* for loop overshoots one */
  159.  
  160.     /* create note first */
  161.     p = create_node(sizeof(FL));
  162.     strncpy(p->fname, f, MAXFLEN);
  163.  
  164.     if (q->head)
  165.       {
  166.       q->head->prev = p;
  167.       p->next = q->head;
  168.       }
  169.     else
  170.       {
  171.       strncpy(q->dname, dir, MAXDLEN);
  172.       }
  173.  
  174.     q->head = p;
  175.     if (!q->tail)
  176.     q->tail = q->head;
  177.  
  178.     return 0;
  179. }
  180.  
  181. static DL *
  182. get_dl(const char *dir)
  183. {
  184.     DL *q = dlist, *qs;
  185.  
  186.     for (qs = q + MAXDIR; q < qs && strcmp(q->dname, dir); q++)
  187.     ;
  188.     return q == qs ? 0 : q;
  189. }
  190.  
  191. static FL *current;        /* current position on FL */
  192.  
  193. int
  194. delete_from_list(const char *dir, const char *f)
  195. {
  196.     FL *p, *e;
  197.     DL *q;
  198.  
  199.     flist_msg("Delete", dir, f);
  200.  
  201.     if (!dir || !f)
  202.     return -1;
  203.  
  204.     if (!(q = get_dl(dir)))
  205.     return -1;
  206.  
  207.     for (p = q->head; p && strcmp(p->fname, f) != 0; p = p->next)
  208.     ;
  209.     if (!p)
  210.     return -1;        /* not found */
  211.  
  212.     e = p;
  213.  
  214.     if (q->head == p)
  215.       {
  216.       if ((q->head = q->head->next))
  217.           q->head->prev = 0;
  218.       else            /* empty list */
  219.           q->tail = 0;
  220.       }
  221.     else if (q->tail == p)
  222.       {
  223.       if ((q->tail = q->tail->prev))
  224.           q->tail->next = 0;
  225.       else
  226.           q->head = 0;
  227.       }
  228.     else
  229.       {                /* remove it */
  230.       p->prev->next = p->next;
  231.       p->next->prev = p->prev;
  232.       }
  233.  
  234.     if (!q->head)
  235.       {                /* this dir is gone */
  236.       q->dname[0] = '\0';    /* and signal so    */
  237.       }
  238.  
  239.     /* if the node happens to be the current node, need to backup one */
  240.     if (current == e)
  241.     current = current->prev;
  242.  
  243.     free_node(e);
  244.  
  245.     return 0;
  246. }
  247.  
  248. int
  249. is_on_list(const char *dir, const char *f)
  250. {
  251.     DL *q = (dir && f) ? get_dl(dir) : 0;
  252.     return q ? (dl_search(q->head, f) != 0) : 0;
  253. }
  254.  
  255. static int pindex;
  256.  
  257. /**********************************************************************
  258.  * Check if current active file list is empty
  259.  **********************************************************************/
  260. int
  261. is_empty_list(void)
  262. {
  263.     int k = 0;
  264.     DL *q = dlist + pindex;
  265.     FL *more = current;
  266.     int imore = pindex;
  267.  
  268.     if (!q->dname[0])
  269.     more = 0;
  270.  
  271.     if (more && (more = more->next))
  272.     return 0;
  273.  
  274.     while (!more && k < MAXDIR)
  275.       {
  276.       ++imore;
  277.       imore %= MAXDIR;
  278.       if ((q = dlist + imore)->head && q->dname[0])
  279.           more = q->head;
  280.       k++;
  281.       }
  282.  
  283.     return more == 0;
  284. }
  285.  
  286.  
  287. const char *
  288. next_file(void)
  289. {
  290.     int k = 0;
  291.     DL *q = dlist + pindex;
  292.  
  293.     if (!q->dname[0])
  294.     current = 0;
  295.     if (current && (current = current->next))
  296.     return current->fname;
  297.  
  298.     while (!current && k < MAXDIR)
  299.       {
  300.       ++pindex;
  301.       pindex %= MAXDIR;
  302.       if ((q = dlist + pindex)->head && q->dname[0])
  303.           current = q->head;
  304.       k++;
  305.       }
  306.  
  307.     if (!current)
  308.       {
  309.       Bark("NextFile", "Empty list");
  310.       return 0;
  311.       }
  312.     else
  313.       {
  314.       chdir(q->dname);
  315.       flist_msg("Next", q->dname, current->fname);
  316.       }
  317.  
  318.     return current->fname;
  319. }
  320.  
  321. const char *
  322. prev_file(void)
  323. {
  324.     int k = 0;
  325.     DL *q = dlist + pindex;
  326.  
  327.     if (!q->dname[0])
  328.     current = 0;
  329.  
  330.     if (current && (current = current->prev))
  331.     return current->fname;
  332.  
  333.     while (!current && k < MAXDIR)
  334.       {
  335.       ++pindex;
  336.       pindex %= MAXDIR;
  337.       if ((q = dlist + pindex)->tail && q->dname[0])
  338.           current = q->tail;
  339.       k++;
  340.       }
  341.  
  342.     if (!current)
  343.       {
  344.       Bark("PrevFile", "Empty list");
  345.       return 0;
  346.       }
  347.     else
  348.       {
  349.       chdir(q->dname);
  350.       flist_msg("Prev", q->dname, current->fname);
  351.       }
  352.  
  353.     return current->fname;
  354. }
  355.  
  356. /****************************************************************
  357.  * given a filename, try to locate the directory it is in
  358.  ****************************************************************/
  359.  
  360. static char *
  361. which_dir(const char *f)
  362. {
  363.     DL *q = dlist, *qs;
  364.  
  365.     for (qs = q + MAXDIR; q < qs && dl_search(q->head, f) == 0; q++)
  366.     ;
  367.     return q ? q->dname : 0;
  368. }
  369.  
  370. /****************************************************************
  371.  * given a filename only, try to delete the file from the list
  372.  ****************************************************************/
  373.  
  374. int
  375. delete_from_list1(const char *f)
  376. {
  377.     char cdir[MAXDLEN + 2];
  378.  
  379.     if (!f)
  380.     return -1;
  381.  
  382.     /* try current directory first */
  383.     getcwd(cdir, MAXDLEN);
  384.  
  385.     /* search list for directory */
  386.     return (delete_from_list(cdir, f) >= 0) ||
  387.     delete_from_list(which_dir(f), f) >= 0;
  388. }
  389.  
  390. int
  391. make_list(int n, char *list[])
  392. {
  393.     static char dirn[MAXDLEN], fn[MAXFLEN];
  394.     int i;
  395.  
  396.     if (n < 1)
  397.     return -1;
  398.  
  399.     if (n > 15)
  400.     show_busy("MakingList ...");
  401.  
  402.     for (i = n; --i >= 0;)
  403.       {
  404.       if (split_fname(dirn, fn, list[i]) == 0)
  405.         {
  406.         if (dirn[strlen(dirn) - 1] != '/')
  407.             strcat(dirn, "/");
  408.         if (fn[0])
  409.             add_to_list(dirn, fn);
  410.         }
  411.       }
  412.     end_busy();
  413.  
  414.     return 0;
  415. }
  416.  
  417. /* empty all lists */
  418. void
  419. cleanup_files(void)
  420. {
  421.     DL *q = dlist, *qs;
  422.  
  423.     for (qs = q + MAXDIR; q < qs; q++)
  424.     if (q->dname[0])
  425.       {
  426.           dl_free(q->head);
  427.           q->dname[0] = '\0';
  428.           q->head = q->tail = 0;
  429.       }
  430. }
  431.